﻿/********************************************************************
	created:	2013/05/02
	created:	2:5:2013   13:54
	filename: 	d:\Lidar\Source\src\GlobalSurface\SplineInterpolation.h
	file path:	d:\Lidar\Source\src\GlobalSurface
	file base:	SplineInterpolation
	file ext:	h
	author:		胡翰
	
	purpose:	输入一个格网化的点云，分块用Thin Plate Spline拟合连续表面

*********************************************************************/
#pragma once
#include <pcl/pcl_base.h>
#include <pcl/point_types.h>
// #include <pcl/search/kdtree.h>
// #include <pcl/kdtree/kdtree_flann.h>

#include "kdtree_flann.h"
#include <Eigen/Core>

#include <vector>
#include <memory>

using namespace std;
using namespace Eigen;
using namespace pcl;

namespace oil
{
class Spline;
typedef vector<Spline, Eigen::aligned_allocator<Spline>> SplineVector;
class RasterSurface;

class SplineInterpolation : public PCLBase<PointXYZ>
{
public:
	typedef PCLBase<PointXYZ>::PointCloud PointCloud;
	typedef PCLBase<PointXYZ>::PointCloudPtr PointCloudPtr;

	using PCLBase<PointXYZ>::indices_;
	using PCLBase<PointXYZ>::input_;

public:
	SplineInterpolation(void);
	~SplineInterpolation(void);

	/*************************************************************************/
	/**
	* @Synopsis		getLambda
	* @Returns		double
	* @remark		获取平滑权值
	*/
	/*************************************************************************/
	double getLambda() const { return lambda_; }

	/*************************************************************************/
	/**
	* @Synopsis		setLambda
	* @Param		double val
	* @Returns		void
	* @remark		设置平滑权值
	*/
	/*************************************************************************/
	void setLambda(double val) { lambda_ = val; }

	/*************************************************************************/
	/**
	* @Synopsis		getSearchSize
	* @Returns		int
	* @remark		获取搜索最邻近单元数目
	*/
	/*************************************************************************/
	int getSearchSize() const { return search_size_; }

	/*************************************************************************/
	/**
	* @Synopsis		setTileWidth
	* @Param		int val
	* @Returns		void
	* @remark		设置最邻近单元数目
	*/
	/*************************************************************************/
	void setSearchSize(int val) { search_size_ = val; }

	/*************************************************************************/
	/**
	* @Synopsis		getMin3D
	* @Returns		Eigen::Vector4f
	* @remark		获取最小点
	*/
	/*************************************************************************/
	Eigen::Vector4f getMin3D() const { return min_; }

	/*************************************************************************/
	/**
	* @Synopsis		setMin3D
	* @Param		const Eigen::Vector4f& & val
	* @Returns		void
	* @remark		设置最小点
	*/
	/*************************************************************************/
	void setMin3D(const Eigen::Vector4f& val) { min_ = val; }

	/*************************************************************************/
	/**
	* @Synopsis		getMax3D
	* @Returns		Eigen::Vector4f
	* @remark		获取最大点
	*/
	/*************************************************************************/
	Eigen::Vector4f getMax3D() const { return max_; }

	/*************************************************************************/
	/**
	* @Synopsis		setMax3D
	* @Param		const Eigen::Vector4f & val
	* @Returns		void
	* @remark		设置最大点
	*/
	/*************************************************************************/
	void setMax3D(const Eigen::Vector4f& val) { max_ = val; }

	/*************************************************************************/
	/**
	* @Synopsis		getWindowSize
	* @Returns		double
	* @remark		获取窗口大小
	*/
	/*************************************************************************/
	double getWindowSize() const { return window_size_; }

	/*************************************************************************/
	/**
	* @Synopsis		setWindowSize
	* @Param		double val
	* @Returns		void
	* @remark		设置窗口大小
	*/
	/*************************************************************************/
	void setWindowSize(double val) { window_size_ = val; }

	/*************************************************************************/
	/**
	* @Synopsis		compute
	* @Returns		void
	* @remark		计算范围内的所有Spline
	*/
	/*************************************************************************/
	void compute();

	void update(const vector<int>& changed_grids);
	/*************************************************************************/
	/**
	* @Synopsis		getZSurface
	* @Returns		RasterSurface*
	* @remark
	*/
	/*************************************************************************/
	RasterSurface* getZSurface() const { return height_surface_.get(); }

	/*************************************************************************/
	/**
	* @Synopsis		getBending
	* @Returns		RasterSurface*
	* @remark
	*/
	/*************************************************************************/
	RasterSurface* getBending() const { return bending_energy_.get(); }

	/*************************************************************************/
	/**
	* @Synopsis		getMask
	* @Returns		RasterSurface*
	* @remark
	*/
	/*************************************************************************/
	RasterSurface* getMask() const { return bending_mask_.get(); }
private:
	void init();

public:
	/// DEM raster
	shared_ptr<RasterSurface> height_surface_;

	/// bending energy
	shared_ptr<RasterSurface> bending_energy_;

	/// mask
	shared_ptr<RasterSurface> bending_mask_;

private:
	/// 平滑阈值
	double lambda_;

	/// 格网的block 大小
	int search_size_;

	/// 包围盒
	Eigen::Vector4f min_;
	Eigen::Vector4f max_;

	/// 格网大小
	double window_size_;

	//Search object
// 	pcl::search::KdTree<PointXY> searcher_;
	KdTreeFLANN<PointXY> searcher_;

	//行数 y
	int rows_;

	//列数 x
	int cols_;

public:
	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};


}//end oil

